#include "StructureGenerator.h"
#include <ctime>
#include <iostream>
#include <fstream>
#include "OptRun.h"
#include "galibFuncs.h"

using namespace std;
using namespace OptRun;

StructureGenerator::StructureGenerator(void)
{
}


StructureGenerator::~StructureGenerator(void)
{
}


int StructureGenerator::LoadDataBase() {



  int i,j;
  clock_t start,finish;
  double totaltime;

  start = clock();



  char filename3[128] = "DataBase.txt";
  //char filename3[128] = "..\\DataBase.txt";
  ifstream inStream(filename3);
  if(!inStream){
    cerr << "Cannot open " << filename3 << " for input.\n";
    exit(1);
  }

  vector<vector<double>> & Holorib = OptInf::Holorib;
  vector<vector<double>> & Cofrasta = OptInf::Cofrasta;
  vector<vector<double>> & CrossSection = OptInf::CrossSection;
  vector<vector<double>> & FullLoad = OptInf::FullLoad;
  vector<vector<double>> & LeftLoad = OptInf::LeftLoad;
  vector<vector<double>> & RightLoad = OptInf::RightLoad;
  vector<vector<double>> & SlabProfile = OptInf::SlabProfile;
  vector<vector<double>> & Five_Span_Load = OptInf::Five_Span_Load;

  vector<std::string> & CrossSectionName = OptInf::CrossSectionName;

  for(int i=0; i<5; i++)
  {
    inStream >> OptInf::ai[i];
  }


  inStream >> OptInf::PopulationSize;
  inStream >> OptInf::GenerationSize;
  inStream >> OptInf::MutationProbability;
  inStream >> OptInf::CrossoverProbability;


  inStream >> OptInf::LENGTH; // the length of the floor 50m
  inStream >> OptInf::WIDTH; // the width of the floor 15m
  inStream >> OptInf::H_MAX; // maximum construction height 600mm
  inStream >> OptInf::X_COL; // the start range of the column position 4.3m.x_col must >= 4.3m
  inStream >> OptInf::Y_COL; // the end range of the column position 5m. y_col must <= 7.5m
  inStream >> OptInf::Dist_COL; //the distance between the columns 0.3m
  OptInf::N_of_Floor = 8;

  for(int i=0; i<OptInf::height1; i++)
  {
    for(int j=0; j<OptInf::width1; j++)
      inStream >> OptInf::CrossSection[i][j];       // read in profile table

    inStream >> OptInf::CrossSectionName[i];
  }

  for(i=0; i<OptInf::height2; i++)
    for(j=0; j<OptInf::width2; j++)
      inStream >> Holorib[i][j]; 

  for(i=0; i<OptInf::height2; i++)
    for(j=0; j<OptInf::width2; j++)
      inStream >> Cofrasta[i][j];
  for(i=0; i<OptInf::height3; i++)
    for(j=0; j<OptInf::width3; j++)
      inStream >> FullLoad[i][j];
  for(i=0; i<OptInf::height3; i++)
    for(j=0; j<OptInf::width3; j++)
      inStream >> LeftLoad[i][j];
  for(i=0; i<OptInf::height3; i++)
    for(j=0; j<OptInf::width3; j++)
      inStream >> RightLoad[i][j];
  for(i=0; i<OptInf::height4; i++)
    for(j=0; j<OptInf::width4; j++)
      inStream >> SlabProfile[i][j];
  for(i=0; i<OptInf::height5; i++)
    for(j=0; j<OptInf::width5; j++)
      inStream >> Five_Span_Load[i][j];

  inStream.close();

  ofstream myfile;
  myfile.open("test.txt");

  //UserData data;  //only for schema gainga
  //data.geo_genome = new GA1DArrayGenome<int>(OptInf::NO_OF_GENE,GaInGa_GeoObjective,(void *)&data);//only for schema gainga
  //   data.pro_genome = new GA1DArrayGenome<int>(OptInf::NO_OF_ProGENE,GaInGa_ProObjective,(void *)&data);//only for schema gainga
  //GA1DArrayGenome<int> genome(*(data.geo_genome));
  //GA1DArrayGenome<int> pro_genome(*(data.pro_genome)); //only for schema gainga
  //genome.initializer(OptRun::GaInGa_GeoInitializer);	
  //genome.mutator(OptRun::GaInGa_GeoMutator);


  GA1DArrayGenome<int> genome(OptInf::NO_OF_GENE, OptRun::ObjectiveGALIB);
  genome.initializer(OptRun::Initializer);
  genome.mutator(OptRun::Mutator);

  //GA1DArrayGenome<int> genome(OptInf::NO_OF_GENE, OptRun::Ga_BFAObjective);
  //genome.initializer(OptRun::Ga_BFAInitializer);
  //genome.mutator(OptRun::Ga_BFAMutator);


  genome.comparator(GA1DArrayGenome<int>::ElementComparator);
  genome.crossover(GA1DArrayGenome<int>::OnePointCrossover);
  //genome.crossover(GA1DArrayGenome<int>::TwoPointCrossover);



  GASteadyStateGA ga(genome);
  //GASimpleGA ga(genome);



  GAParameterList params;
  GASteadyStateGA::registerDefaultParameters(params);
  //params.set(gaNpopulationSize, 1000);    // number of individuals in population
  //params.set(gaNpCrossover, 0.9);       // likelihood of doing crossover
  //params.set(gaNpMutation, 0.05);	// probability of mutation
  //params.set(gaNnGenerations, 200);	// number of generations
  params.set(gaNscoreFrequency, 200);	// how often to record scores
  params.set(gaNflushFrequency, 500);    // how often to flush scores to file
  params.set(gaNscoreFilename, "bogflushScores.dat");
  //params.parse(argc, argv, gaFalse);
  ga.parameters(params);




  ga.minimize();
  //ga.maximize();
  //ga.populationSize(1000);
  //ga.nGenerations(1000);

  ga.populationSize(OptInf::PopulationSize);
  ga.nGenerations(OptInf::GenerationSize);
  ga.populationSize(1000);
  ga.nGenerations(3000);



  ga.pMutation(0.05);
  ////ga.pCrossover(1);
  ga.pCrossover(0.95);
  ga.pConvergence(2-0.99);
  ga.nConvergence(1000);
  //ga.terminator(GAGeneticAlgorithm::TerminateUponConvergence);
  ga.selectScores(GAStatistics::AllScores);
  //ga.parameters(argc, argv, gaTrue);
  //ga.terminator(GAGeneticAlgorithm::TerminateUponGeneration);
  //ga.terminator(GAGeneticAlgorithm::TerminateUponPopConvergence);
  ga.terminator(GAGeneticAlgorithm::TerminateUponConvergence);
  //ga.terminator(GAGeneticAlgorithm::TerminateUponGeneration);
  //ga.terminator(GAGeneticAlgorithm::TerminateUponConvergence);

  cout<<"population size: "<<ga.populationSize()<<"\n";
  cout<<"generation size: "<<ga.nGenerations()<<"\n";

  ga.initialize();

  OptInf info;

  //OptRun::Ga_BFAInitializer(genome);
  //GASchema gaS = OptRun::GASchema::GA_BFA;
  //myfile<<"GASchema: GA_BFA"<<"\n";

  OptRun::Initializer(genome);
  GASchema gaS = OptRun::GASchema::OneGA;
  myfile<<"GASchema: OneGA"<<"\n";

  //OptRun::GaInGa_GeoInitializer(genome);
  //GASchema gaS = OptRun::GASchema::GAinGA;
  //myfile<<"GASchema: GAinGA"<<"\n";

  start = clock();

  //ga.terminator(GAGeneticAlgorithm::TerminateUponGeneration);
  //ga.evolve();

  int iG = 0;
  while (!ga.done()){

    genome = ga.statistics().bestIndividual();
    //cout << ga.generation() << " "<<genome<<" "<<OptRun::Ga_BFAObjective(genome)<<endl;//cout.flush();
    //cout << ga.generation() << " "<<genome<<" "<<OptRun::Objective(genome)<<endl;//cout.flush();
    //cout<<ga.generation() << " "<<genome<<" "<<genome.score()<<endl;
    //myfile<<ga.generation() << " "<<genome.score()<<" "<<genome<<endl;
    //cout << ga.generation() << " "<<genome<<*data.pro_genome<<" "<<OptRun::GaInGa_GeoObjective(genome)<<endl;//cout.flush();
    //myfile<< ga.generation() << " "<<genome<<*data.pro_genome<<" "<<OptRun::GaInGa_GeoObjective(genome)<<endl;//cout.flush();
    //myfile<<ga.generation() << " "<<OptRun::Ga_BFAObjective(genome)<<" "<<genome;

    UpdateInfoObjective(info, genome );
    CallOptInformation(info, genome );

    //float a = OptRun::ObjectiveGALIB(genome);
    //cout << a;
    //UpdateInfoObjective(info, genome,gaS ); // tempary

    //cout<<" PenaltyWeight= "<<info.PenaltyWeight<<endl;
    //myfile<<"M_yEd_sec/M_plRd_se= "<<info.M_yEd_sec/info.M_plRd_sec<<" V_Ed_sec/V_plRd_sec= "<<info.V_Ed_sec/info.V_plRd_sec<<" Deflection_sec/LengthSecBeam_3_5= "<<info.Deflection_sec/info.LengthSecBeam_3_5<<endl;
    //myfile<<"M_yEd_neg_pri/M_plRd_neg_pri= "<<info.M_yEd_neg_pri/info.M_plRd_neg_pri<<"V_Ed_pri/V_plRd_pri= "<<info.V_Ed_pri/info.V_plRd_pri<<" M_yEd_pos_pri/M_plRd_pos_pri= "<<info.M_yEd_pos_pri/info.M_plRd_pos_pri<<endl;
    //myfile<<"F_Ed_m/N_b_y_Rd= "<<info.F_Ed_m/info.N_b_y_Rd<<" F_Ed_e/N_b_y_Rd+k_yy*M_Ed_y_col/M_b_y_Rd= "<<info.F_Ed_e/info.N_b_y_Rd+info.k_yy*info.M_Ed_y_col/info.M_b_y_Rd<<"  F_Ed_e/N_b_z_Rd+k_zy*M_Ed_y_col/M_b_y_Rd= "<<info.F_Ed_e/info.N_b_z_Rd+info.k_zy*info.M_Ed_y_col/info.M_b_y_Rd<<endl;
    //cout<<info.N_b_y_Rd<<endl;
    //cout << ga.generation() << " "<< info.fit <<endl;

    if(iG++%500 == 0)
    {
      cout << ga.generation()<<"-> " <<genome << "  \t-> "<<genome.score()<<"\n";  
      myfile << ga.generation()<<"-> " <<genome << "  \t-> "<<genome.score()<<"\n";  

      cout << "N_of_Floor: " << OptInf::N_of_Floor << "    ( " << OptInf::LENGTH << " m  x " << OptInf::WIDTH << "m ) \n" << "load_e  "<< OptInf::load_e << "  \t load_m  "<< OptInf::load_m <<   "\n";

      myfile << "N_of_Floor: " << OptInf::N_of_Floor << "    ( " << OptInf::LENGTH << " m  x " << OptInf::WIDTH << "m ) \n" << "load_e  "<< OptInf::load_e << "  \t load_m  "<< OptInf::load_m <<   "\n";

      cout << "M_2: "<<OptInf::MyEdsec_o_MplRdsec <<"  \t "
        << "V_2: "<<OptInf::VEdsec_o_VplRdsec <<"  \t "
        << "Def_2: "<<OptInf::Deflectionsec_o_LengthSecBeam3o5 <<"  \t "
        << "M_1: "<<OptInf::MyEdpospri_o_MplRdpospri <<"  \t "
        << "V_1: "<< OptInf::VEdpri_o_VplRdpri<<"  \t"
        << "H_2: " << OptInf::CrossSection[genome.gene(4)][1] << "\t"
        << "H_1: " << OptInf::CrossSection[genome.gene(6)][1] << "\t"
        << "Penalty: " << OptInf::PenaltyTotal << "  \t\n";
      myfile << "M_2: "<<OptInf::MyEdsec_o_MplRdsec <<"  \t "
        << "V_2: "<<OptInf::VEdsec_o_VplRdsec <<"  \t "
        << "Def_2: "<<OptInf::Deflectionsec_o_LengthSecBeam3o5 <<"  \t "
        << "M_1: "<<OptInf::MyEdpospri_o_MplRdpospri <<"  \t "
        << "V_1: "<< OptInf::VEdpri_o_VplRdpri<<"  \t"
        << "H_2: " << OptInf::CrossSection[genome.gene(4)][1] << "\t"
        << "H_1: " << OptInf::CrossSection[genome.gene(6)][1] << "\t"
        << "Penalty: " << OptInf::PenaltyTotal << "  \t\n";


      if (genome.gene(8) == 0)
      {
        cout << "transverse\n";
        myfile << "transverse\n";
      } 
      else
      {
        cout << "longitudinal\n";
        myfile << "longitudinal\n";
      }

      cout << "2nd "<< genome.gene(4)<<": "<< OptInf::CrossSectionName[genome.gene(4)] << " \t 1st "<< genome.gene(4)<<": "<< OptInf::CrossSectionName[genome.gene(6)] << "\n";
      myfile << "2nd "<< genome.gene(4)<<": "<< OptInf::CrossSectionName[genome.gene(4)] << " \t 1st "<< genome.gene(6)<<": "<< OptInf::CrossSectionName[genome.gene(6)] << "\n";
      for(int i=0;i<OptInf::N_of_Floor;i++)
      {
        cout << "( "<< genome.gene(11+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(11+i*4)] << " - " << OptInf::CrossSection[genome.gene(11+i*4)][10] << "  &  " 
          << genome.gene(12+i*4) << " )  \t" << OptInf::FEdm_o_NbyRd_m[i] << "  \t"
          << "( "<< genome.gene(13+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(13+i*4)] << " - " << OptInf::CrossSection[genome.gene(13+i*4)][10] << "  &  " 
          << genome.gene(14+i*4) << " )  \t" << OptInf::FEde_o_NbyRd_add_kyy_t_MEdy_o_MbyRd_e[i]  << " , "<<OptInf::FEde_o_NbzRd_add_kzy_t_MEdy_o_MbyRd_e[i] << "\n";
        myfile << "( "<< genome.gene(11+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(11+i*4)] << " - " << OptInf::CrossSection[genome.gene(11+i*4)][10] << "  &  " 
          << genome.gene(12+i*4) << " )  \t" << OptInf::FEdm_o_NbyRd_m[i] << "  \t"
          << "( "<< genome.gene(13+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(13+i*4)] << " - " << OptInf::CrossSection[genome.gene(13+i*4)][10] << "  &  " 
          << genome.gene(14+i*4) << " )  \t" << OptInf::FEde_o_NbyRd_add_kyy_t_MEdy_o_MbyRd_e[i]  << " , " << OptInf::FEde_o_NbzRd_add_kzy_t_MEdy_o_MbyRd_e[i] << "\n";
      }
      cout << "\n\n";
      myfile << "\n\n";
    }
    //cout << ga.statistics().convergence() << "\n";
    ++ga;
  }  


  ga.flushScores();

  finish = clock();
  totaltime = (double)(finish-start)/CLOCKS_PER_SEC;

  //ga.evolve();
  genome=ga.statistics().bestIndividual();
  cout << "Best individual is " <<ga.statistics().bestIndividual() << " Fitness = "<<genome.score()<<"\n\n";  
  myfile << "Best individual is " <<ga.statistics().bestIndividual() << " Fitness = "<<genome.score()<<"\n\n";  
  //myfile<<genome.score()<<" ";
  cout<< ga.statistics() << "\n";
  myfile << ga.statistics() << "\n";
  cout<<"processing time is : "<<totaltime<<" sec.\n";
  myfile <<"processing time is : "<<totaltime<<" sec.\n";

  //int steelGradeArray[] = {235,355,460};
  cout << "Best individual is " <<ga.statistics().bestIndividual() << " Fitness = "<<genome.score()<<"\n\n";  
  myfile << "Best individual is " <<ga.statistics().bestIndividual() << " Fitness = "<<genome.score()<<"\n\n";  

  cout << "N_of_Floor: " << OptInf::N_of_Floor << "    ( " << OptInf::LENGTH << " m  x " << OptInf::WIDTH << "m ) \n" << "load_e  "<< OptInf::load_e << "  \t load_m  "<< OptInf::load_m <<   "\n";
  myfile << "N_of_Floor: " << OptInf::N_of_Floor << "    ( " << OptInf::LENGTH << " m  x " << OptInf::WIDTH << "m ) \n" << "load_e  "<< OptInf::load_e << "  \t load_m  "<< OptInf::load_m <<   "\n";
  cout << "2nd "<< genome.gene(4)<<":"<< OptInf::CrossSectionName[genome.gene(4)] << " \t 1st "<< genome.gene(4)<<":"<< OptInf::CrossSectionName[genome.gene(6)] << "\n";
  myfile << "2nd "<< genome.gene(4)<<":"<< OptInf::CrossSectionName[genome.gene(4)] << " \t 1st "<< genome.gene(6)<<":"<< OptInf::CrossSectionName[genome.gene(6)] << "\n";


  cout << "M_2: "<<OptInf::MyEdsec_o_MplRdsec <<"  \t "
    << "V_2: "<<OptInf::VEdsec_o_VplRdsec <<"  \t "
    << "Def_2: "<<OptInf::Deflectionsec_o_LengthSecBeam3o5 <<"  \t "
    << "M_1: "<<OptInf::MyEdpospri_o_MplRdpospri <<"  \t "
    << "V_1: "<< OptInf::VEdpri_o_VplRdpri<<"  \t"
    << "H_2: " << OptInf::CrossSection[genome.gene(4)][1] << "\t"
    << "H_1: " << OptInf::CrossSection[genome.gene(6)][1] << "\t"
    << "Penalty: " << OptInf::PenaltyTotal << "  \t\n";
  myfile << "M_2: "<<OptInf::MyEdsec_o_MplRdsec <<"  \t "
    << "V_2: "<<OptInf::VEdsec_o_VplRdsec <<"  \t "
    << "Def_2: "<<OptInf::Deflectionsec_o_LengthSecBeam3o5 <<"  \t "
    << "M_1: "<<OptInf::MyEdpospri_o_MplRdpospri <<"  \t "
    << "V_1: "<< OptInf::VEdpri_o_VplRdpri<<"  \t"
    << "H_2: " << OptInf::CrossSection[genome.gene(4)][1] << "\t"
    << "H_1: " << OptInf::CrossSection[genome.gene(6)][1] << "\t"
    << "Penalty: " << OptInf::PenaltyTotal << "  \t\n";

  for(int i=0;i<OptInf::N_of_Floor;i++)
  {
    cout << "( "<< genome.gene(11+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(11+i*4)] << " - " << OptInf::CrossSection[genome.gene(11+i*4)][10] << "  &  " 
      << genome.gene(12+i*4) << " )  \t" << OptInf::FEdm_o_NbyRd_m[i] << "  \t"
      << "( "<< genome.gene(13+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(13+i*4)] << " - " << OptInf::CrossSection[genome.gene(13+i*4)][10] << "  &  " 
      << genome.gene(14+i*4) << " )  \t" << OptInf::FEde_o_NbyRd_add_kyy_t_MEdy_o_MbyRd_e[i]  << " , "<<OptInf::FEde_o_NbzRd_add_kzy_t_MEdy_o_MbyRd_e[i] << "\n";

    myfile << "( "<< genome.gene(11+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(11+i*4)] << " - " << OptInf::CrossSection[genome.gene(11+i*4)][10] << "  &  " 
      << genome.gene(12+i*4) << " )  \t" << OptInf::FEdm_o_NbyRd_m[i] << "  \t"
      << "( "<< genome.gene(13+i*4)<<":"<< OptInf::CrossSectionName[genome.gene(13+i*4)] << " - " << OptInf::CrossSection[genome.gene(13+i*4)][10] << "  &  " 
      << genome.gene(14+i*4) << " )  \t" << OptInf::FEde_o_NbyRd_add_kyy_t_MEdy_o_MbyRd_e[i]  << " , "<<OptInf::FEde_o_NbzRd_add_kzy_t_MEdy_o_MbyRd_e[i] << "\n";
  }


  myfile.close();

  //system("PAUSE");
  return 0;
}